반정규화
개요
정규화가 오히려 성능과 유지보수에 저해되는 경우가 있을 수 있다.
이럴 때 오히려 중복, 통합 등의 작업을 수행하는 것이 반정규화이다.
대체로 조회 성능을 올리기 향상하기 위한 방법으로 활용된다.
가끔은 데이터를 중복 저장하는 것이 조인 연산 회피로 인한 성능 향상을 일으킬 수 있는 것이다.
결국 이것은 데이터 무결성을 해친다.
그럼에도 다음과 같은 상황을 위해 반정규화를 하게 될 수 있다.
- 데이터 조회 시 디스크 I/O량이 너무 많아 성능이 저하
- 테이블 간 경로가 멀어 중복 조인으로 인한 성능 저하
- 칼럼을 계산한 값을 도출해야 할 때 성능 저하
분명한 점은 결국 반정규화는 관리의 비용을 크게 증가시킬 수 있다는 것이다.
그래서 운영 중에 신중하게 도입돼야 한다.
절차
일단 반정규화가 필요한 대상을 조사한다.
- 범위 처리 빈도수 조사
- 대량 범위 처리 조사
- 통계성 프로세스 조사
- 테이블 조인 개수
이후에는 다른 방법이 없는지 먼저 검토한다.
- 뷰 테이블
- 클러스터링 적용
- 인덱스 조정
- 앱 로직 변경
이래도 방법이 없다면, 테이블, 칼럼, 관계를 중복시키는 방법으로 반정규화를 달성하게 된다.
테이블 반정규화
세부적으로 다음의 방법이 있다.
테이블 병합
1:1 관계, 1:M 관계, 혹은 슈버/서브 타입의 테이블을 병합한다.
슈퍼/서브는 다음에 본다.
이 방법들은 조인 연산을 없애는데 초점을 둔다.
테이블 분할
수직 분할
칼럼이 준나 많다면, 디스크 I/O를 분산 처리하기 위해 도입할 수 있는 방법이다.
게시글 테이블의 조회수 칼럼은 아예 테이블을 분리하여 관리하는 식이다.
이렇게 테이블을 분할하면 테이블들이 서로 1:1 관계라는 특징이 있다.
수평 분할(파티셔닝)
수평 분할은 파티셔닝이라고 부른다.
행이 준나 많다면, 트랜잭션을 분석하고 쪼개서 데이터 접근 효율을 높인다.
요금납무 테이블을 년,월,일 별로 테이블을 분리하는 식으로.
여기에서도 몇 가지 방법이 있다.
범위 파티셔닝
기간으로 행을 분할한다.
연속적인 데이터에 대해 유용하다.
이게 좋은 점은 오래된 데이터가 필요없다면 그냥 쉽게 날려먹을 수 있다.
리스트 파티셔닝
이건 다른 행을 기준으로 파티셔닝을 하는 것을 말한다.
고객 테이블이 많다면, 지역 별로 파티셔닝을 하는 것.
이산적이고 도메인 범위가 확실한 데이터에 대해 유용하다.
이것도 나누는 기준에 따른 쿼리가 많을 때 유용하다.
해시 파티셔닝
지정된 해시 조건을 활용해 파티셔닝한다.
이건 나뉘는 테이블들에 고루고루 데이터를 쳐박고 싶을 때 쓴다.
데이터 입력이 한 테이블에 자주 일어나 경합으로 인한 성능 부하가 생기는 경우는 거의 없다.
주민번호처럼 변별력이 뛰어난 칼럼이 있다면 도입해볼 만하다.
대신 단점도 있다.
관리자는 어디에 어떤 데이터가 들어가는지 가늠이 어렵다.
데이터 보관 주기에 따라 삭제하는 기능을 제공하기 어렵다.
테이블 추가
- 중복 테이블
- 물리적 위치가 다를 때 아예 원격 조인을 없애버리기 위해
- 통계 테이블
- sum, avg가 많이 쓰이면 아예 따로 테이블 추가
- 이력 테이블
- 부분 테이블
- 자주 사용되는 칼럼만 테이블로 분리
칼럼 반정규화
- 중복 칼럼
- 조인 연산 성능 저하 방지
- 2 정규화로 분리는 했는데, 그래도 성능저하가 있다면 다시 원래 테이블로 붙이는 게 나을 때도 있다..
- 파생 칼럼
- 트랜잭션이 처리될 때 계산되어 발생하는 값이 있다면 미리 계산해서 저장하기
- 위의 통계 테이블 추가하는 것과 거의같다.
- 이력 테이블 칼럼
- 대량의 히스토리관련에 대해서는 최근 값 여부, 시작일자 등을 따로 칼럼으로 두는 게 나을 때도 있다.
- PK에 의한 칼럼
- 복합 기본키인 테이블에 대해 그냥 단일 기본키를 별도로 두는 게 나을 때도 있다.
- 응용 시스템 오작동을 위한 칼럼
- 비즈니스적으로는 의미가 없다.
- 그러나 사용자의 잘못된 데이터 처리가 있어서 원래 값으로 복구할 때를 위해 데이터를 임시 중복 보관하는 경우
- 이걸 그냥 히스토리 데이터로 만들어버리면 정상적인 데이터 모델이 된다.
관계 비정규화
여기에는 중복 관계를 추가하는 방법이 있다.
원래는 여러 테이블을 조인해서 얻어야 하는 값이라면, 그냥 아예 관계를 새로 추가해서 접근하는 식으로 풀어낼 수가 있다.
이건 테이블, 칼럼 반정규화와 다르게 데이터 무결성을 깨뜨리지 않고도 처리 성능을 향상시킬 수 있다.